"""
报告导出工具
支持 PDF 和 Excel 格式导出
"""
from io import BytesIO
from datetime import datetime
from typing import Any, Dict, List
import os
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, PageBreak
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.chart import BarChart, PieChart, RadarChart, Reference
from openpyxl.chart.label import DataLabelList


# 注册中文字体
def register_chinese_fonts():
    """注册中文字体"""
    # Windows 系统字体路径
    windows_fonts = [
        r'C:\Windows\Fonts\simhei.ttf',  # 黑体
        r'C:\Windows\Fonts\simsun.ttc',  # 宋体
        r'C:\Windows\Fonts\msyh.ttc',    # 微软雅黑
    ]
    
    # Linux 系统字体路径
    linux_fonts = [
        '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
        '/usr/share/fonts/truetype/arphic/uming.ttc',
    ]
    
    # macOS 系统字体路径
    mac_fonts = [
        '/System/Library/Fonts/PingFang.ttc',
        '/Library/Fonts/Arial Unicode.ttf',
    ]
    
    all_fonts = windows_fonts + linux_fonts + mac_fonts
    
    for font_path in all_fonts:
        if os.path.exists(font_path):
            try:
                pdfmetrics.registerFont(TTFont('ChineseFont', font_path))
                return True
            except:
                continue
    
    return False


# 尝试注册中文字体
_font_registered = register_chinese_fonts()


class ReportExporter:
    """报告导出器"""
    
    @staticmethod
    def export_to_pdf(report_data: Dict[str, Any]) -> BytesIO:
        """
        导出为 PDF 格式
        
        Args:
            report_data: 报告数据
            
        Returns:
            BytesIO: PDF 文件流
        """
        buffer = BytesIO()
        
        # 创建PDF文档
        doc = SimpleDocTemplate(
            buffer,
            pagesize=A4,
            rightMargin=2*cm,
            leftMargin=2*cm,
            topMargin=2*cm,
            bottomMargin=2*cm
        )
        
        # 准备内容
        story = []
        styles = getSampleStyleSheet()
        
        # 获取字体名称
        font_name = 'ChineseFont' if _font_registered else 'Helvetica'
        
        # 创建自定义样式（支持中文）
        title_style = ParagraphStyle(
            'CustomTitle',
            parent=styles['Heading1'],
            fontName=font_name,
            fontSize=24,
            textColor=colors.HexColor('#1890ff'),
            spaceAfter=30,
            alignment=TA_CENTER,
        )
        
        heading_style = ParagraphStyle(
            'CustomHeading',
            parent=styles['Heading2'],
            fontName=font_name,
            fontSize=16,
            textColor=colors.HexColor('#333333'),
            spaceAfter=12,
            spaceBefore=12,
        )
        
        normal_style = ParagraphStyle(
            'CustomNormal',
            parent=styles['Normal'],
            fontName=font_name,
            fontSize=10,
            leading=14,
        )
        
        # 标题
        story.append(Paragraph("病历质量评估报告", title_style))
        story.append(Spacer(1, 0.5*cm))
        
        # 基本信息
        assessment = report_data.get('assessment', {})
        record = report_data.get('record', {})
        statistics = report_data.get('statistics', {})
        
        story.append(Paragraph("患者基本信息", heading_style))
        
        patient_data = [
            ['姓名', record.get('patient_name', '-')],
            ['性别', record.get('patient_gender', '-')],
            ['年龄', str(record.get('patient_age', '-'))],
            ['科室', record.get('department', '-')],
            ['就诊日期', record.get('visit_date', '-')[:10] if record.get('visit_date') else '-'],
            ['医生', record.get('doctor_name', '-')],
        ]
        
        patient_table = Table(patient_data, colWidths=[5*cm, 12*cm])
        patient_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#f0f0f0')),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, -1), font_name),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
            ('TOPPADDING', (0, 0), (-1, -1), 8),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ]))
        story.append(patient_table)
        story.append(Spacer(1, 0.5*cm))
        
        # 评估概况
        story.append(Paragraph("评估概况", heading_style))
        
        overview_data = [
            ['综合评分', f"{assessment.get('overall_score', 0)} / 100"],
            ['完整性', f"{assessment.get('completeness_score', 0)} / 100"],
            ['规范性', f"{assessment.get('standardization_score', 0)} / 100"],
            ['一致性', f"{assessment.get('consistency_score', 0)} / 100"],
            ['准确性', f"{assessment.get('accuracy_score', 0)} / 100"],
        ]
        
        overview_table = Table(overview_data, colWidths=[8*cm, 9*cm])
        overview_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#f0f0f0')),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
            ('ALIGN', (0, 0), (0, -1), 'LEFT'),
            ('ALIGN', (1, 0), (1, -1), 'RIGHT'),
            ('FONTNAME', (0, 0), (-1, -1), font_name),
            ('FONTSIZE', (0, 0), (-1, -1), 11),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 10),
            ('TOPPADDING', (0, 0), (-1, -1), 10),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ]))
        story.append(overview_table)
        story.append(Spacer(1, 0.5*cm))
        
        # 统计信息
        story.append(Paragraph("问题统计", heading_style))
        
        stats_data = [
            ['总问题数', str(statistics.get('total_issues', 0))],
            ['严重问题', str(statistics.get('critical_issues', 0))],
            ['主要问题', str(statistics.get('major_issues', 0))],
            ['次要问题', str(statistics.get('minor_issues', 0))],
        ]
        
        stats_table = Table(stats_data, colWidths=[8*cm, 9*cm])
        stats_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#f0f0f0')),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
            ('ALIGN', (0, 0), (0, -1), 'LEFT'),
            ('ALIGN', (1, 0), (1, -1), 'RIGHT'),
            ('FONTNAME', (0, 0), (-1, -1), font_name),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
            ('TOPPADDING', (0, 0), (-1, -1), 8),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ]))
        story.append(stats_table)
        story.append(Spacer(1, 0.5*cm))
        
        # 评估总结
        if assessment.get('summary'):
            story.append(Paragraph("评估总结", heading_style))
            story.append(Paragraph(assessment.get('summary', ''), normal_style))
            story.append(Spacer(1, 0.3*cm))
        
        # 改进建议
        if assessment.get('suggestions') and len(assessment.get('suggestions', [])) > 0:
            story.append(Paragraph("改进建议", heading_style))
            for idx, suggestion in enumerate(assessment.get('suggestions', []), 1):
                story.append(Paragraph(f"{idx}. {suggestion}", normal_style))
            story.append(Spacer(1, 0.3*cm))
        
        # 问题详情
        issues = assessment.get('issues', [])
        if issues:
            story.append(PageBreak())
            story.append(Paragraph("问题详情", heading_style))
            
            issue_data = [['类型', '严重程度', '字段', '描述', '扣分']]
            
            for issue in issues:
                issue_type = ReportExporter._get_issue_type_name(issue.get('issue_type', ''))
                severity = ReportExporter._get_severity_name(issue.get('severity', ''))
                field = issue.get('field_name', '-')[:20]
                desc = issue.get('issue_description', '')[:40]
                deduction = str(issue.get('score_deduction', 0))
                
                issue_data.append([issue_type, severity, field, desc, f"-{deduction}"])
            
            issue_table = Table(issue_data, colWidths=[3*cm, 2.5*cm, 3*cm, 6.5*cm, 2*cm])
            issue_table.setStyle(TableStyle([
                ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1890ff')),
                ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
                ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                ('FONTNAME', (0, 0), (-1, -1), font_name),
                ('FONTSIZE', (0, 0), (-1, 0), 10),
                ('FONTSIZE', (0, 1), (-1, -1), 9),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
                ('TOPPADDING', (0, 0), (-1, -1), 6),
                ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
                ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.HexColor('#f9f9f9')]),
            ]))
            story.append(issue_table)
        
        # 生成PDF
        doc.build(story)
        buffer.seek(0)
        return buffer
    
    @staticmethod
    def export_to_excel(report_data: Dict[str, Any]) -> BytesIO:
        """
        导出为 Excel 格式
        
        Args:
            report_data: 报告数据
            
        Returns:
            BytesIO: Excel 文件流
        """
        buffer = BytesIO()
        wb = Workbook()
        
        # 删除默认工作表
        wb.remove(wb.active)
        
        assessment = report_data.get('assessment', {})
        record = report_data.get('record', {})
        statistics = report_data.get('statistics', {})
        charts_data = report_data.get('charts_data', {})
        
        # 创建样式
        header_fill = PatternFill(start_color='1890FF', end_color='1890FF', fill_type='solid')
        header_font = Font(bold=True, color='FFFFFF', size=12)
        title_font = Font(bold=True, size=14)
        border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        # 1. 概览工作表
        ws_overview = wb.create_sheet("概览")
        
        # 标题
        ws_overview['A1'] = '病历质量评估报告'
        ws_overview['A1'].font = Font(bold=True, size=16, color='1890FF')
        ws_overview.merge_cells('A1:D1')
        ws_overview['A1'].alignment = Alignment(horizontal='center')
        
        # 患者信息
        ws_overview['A3'] = '患者基本信息'
        ws_overview['A3'].font = title_font
        ws_overview.merge_cells('A3:B3')
        
        patient_info = [
            ['姓名', record.get('patient_name', '-')],
            ['性别', record.get('patient_gender', '-')],
            ['年龄', record.get('patient_age', '-')],
            ['科室', record.get('department', '-')],
            ['就诊日期', record.get('visit_date', '-')[:10] if record.get('visit_date') else '-'],
            ['医生', record.get('doctor_name', '-')],
        ]
        
        for idx, (label, value) in enumerate(patient_info, start=4):
            ws_overview[f'A{idx}'] = label
            ws_overview[f'B{idx}'] = value
            ws_overview[f'A{idx}'].font = Font(bold=True)
        
        # 评估概况
        overview_row = len(patient_info) + 5
        ws_overview[f'A{overview_row}'] = '评估概况'
        ws_overview[f'A{overview_row}'].font = title_font
        ws_overview.merge_cells(f'A{overview_row}:B{overview_row}')
        
        overview_row += 1
        scores = [
            ['综合评分', assessment.get('overall_score', 0)],
            ['完整性', assessment.get('completeness_score', 0)],
            ['规范性', assessment.get('standardization_score', 0)],
            ['一致性', assessment.get('consistency_score', 0)],
            ['准确性', assessment.get('accuracy_score', 0)],
        ]
        
        for idx, (label, score) in enumerate(scores, start=overview_row):
            ws_overview[f'A{idx}'] = label
            ws_overview[f'B{idx}'] = score
            ws_overview[f'A{idx}'].font = Font(bold=True)
            ws_overview[f'B{idx}'].number_format = '0'
        
        # 统计信息
        stats_row = overview_row + len(scores) + 1
        ws_overview[f'A{stats_row}'] = '问题统计'
        ws_overview[f'A{stats_row}'].font = title_font
        ws_overview.merge_cells(f'A{stats_row}:B{stats_row}')
        
        stats_row += 1
        stats_info = [
            ['总问题数', statistics.get('total_issues', 0)],
            ['严重问题', statistics.get('critical_issues', 0)],
            ['主要问题', statistics.get('major_issues', 0)],
            ['次要问题', statistics.get('minor_issues', 0)],
        ]
        
        for idx, (label, value) in enumerate(stats_info, start=stats_row):
            ws_overview[f'A{idx}'] = label
            ws_overview[f'B{idx}'] = value
            ws_overview[f'A{idx}'].font = Font(bold=True)
        
        # 设置列宽
        ws_overview.column_dimensions['A'].width = 20
        ws_overview.column_dimensions['B'].width = 30
        
        # 2. 问题详情工作表
        ws_issues = wb.create_sheet("问题详情")
        
        # 表头
        headers = ['类型', '严重程度', '字段名称', '问题描述', '改进建议', '扣分']
        for idx, header in enumerate(headers, start=1):
            cell = ws_issues.cell(row=1, column=idx)
            cell.value = header
            cell.fill = header_fill
            cell.font = header_font
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = border
        
        # 数据
        issues = assessment.get('issues', [])
        for row_idx, issue in enumerate(issues, start=2):
            ws_issues.cell(row=row_idx, column=1).value = ReportExporter._get_issue_type_name(
                issue.get('issue_type', '')
            )
            ws_issues.cell(row=row_idx, column=2).value = ReportExporter._get_severity_name(
                issue.get('severity', '')
            )
            ws_issues.cell(row=row_idx, column=3).value = issue.get('field_name', '-')
            ws_issues.cell(row=row_idx, column=4).value = issue.get('issue_description', '')
            ws_issues.cell(row=row_idx, column=5).value = issue.get('suggestion', '-')
            ws_issues.cell(row=row_idx, column=6).value = issue.get('score_deduction', 0)
            
            # 应用边框
            for col in range(1, 7):
                ws_issues.cell(row=row_idx, column=col).border = border
        
        # 设置列宽
        ws_issues.column_dimensions['A'].width = 15
        ws_issues.column_dimensions['B'].width = 12
        ws_issues.column_dimensions['C'].width = 20
        ws_issues.column_dimensions['D'].width = 40
        ws_issues.column_dimensions['E'].width = 40
        ws_issues.column_dimensions['F'].width = 10
        
        # 3. 图表数据工作表
        ws_charts = wb.create_sheet("图表数据")
        
        # 维度评分数据
        ws_charts['A1'] = '维度'
        ws_charts['B1'] = '评分'
        ws_charts['A1'].font = header_font
        ws_charts['B1'].font = header_font
        
        dimensions = ['完整性', '规范性', '一致性', '准确性']
        scores_values = [
            assessment.get('completeness_score', 0),
            assessment.get('standardization_score', 0),
            assessment.get('consistency_score', 0),
            assessment.get('accuracy_score', 0),
        ]
        
        for idx, (dim, score) in enumerate(zip(dimensions, scores_values), start=2):
            ws_charts[f'A{idx}'] = dim
            ws_charts[f'B{idx}'] = score
        
        # 创建柱状图
        chart = BarChart()
        chart.title = "维度评分对比"
        chart.x_axis.title = "维度"
        chart.y_axis.title = "评分"
        
        data = Reference(ws_charts, min_col=2, min_row=1, max_row=5)
        cats = Reference(ws_charts, min_col=1, min_row=2, max_row=5)
        chart.add_data(data, titles_from_data=True)
        chart.set_categories(cats)
        
        ws_charts.add_chart(chart, "D2")
        
        # 设置列宽
        ws_charts.column_dimensions['A'].width = 20
        ws_charts.column_dimensions['B'].width = 15
        
        # 保存到内存
        wb.save(buffer)
        buffer.seek(0)
        return buffer
    
    @staticmethod
    def _get_issue_type_name(issue_type: str) -> str:
        """获取问题类型中文名"""
        type_map = {
            'completeness': '完整性',
            'standardization': '规范性',
            'consistency': '一致性',
            'accuracy': '准确性',
        }
        return type_map.get(issue_type, issue_type)
    
    @staticmethod
    def _get_severity_name(severity: str) -> str:
        """获取严重程度名称"""
        severity_map = {
            'critical': '严重',
            'major': '主要',
            'minor': '次要',
            'info': '提示',
        }
        return severity_map.get(severity, severity)

